package com.net.server.netty;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.LengthFieldPrepender;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.HashedWheelTimer;


public class ServerPipelineFactory implements ChannelPipelineFactory {

	/**
	 * 超时时间
	 */
	private int sessionIdleTime;
	
	/**
	 * 添加最大连接数
	 */
	private final DefaultFirewallFilter firewallFilter;
	
	private final ExecutionHandler executionHandler;
	
	private final IdleStateHandler idleStateHandler;
	
	public ServerPipelineFactory(int sessionIdleTime, ExecutionHandler executionHandler) {
		super();
		this.setSessionIdleTime(sessionIdleTime);
		this.firewallFilter = new DefaultFirewallFilter();
		this.executionHandler = executionHandler;
		this.idleStateHandler = new IdleStateHandler(new HashedWheelTimer(), 0, 0, sessionIdleTime);
	}

	@Override
	public ChannelPipeline getPipeline() throws Exception {
		ChannelPipeline pipeline = Channels.pipeline();
		pipeline.addFirst("firewall", firewallFilter);// 过滤Ip/连接数统计
		//pipeline.addLast("decoder", new ByteBufferDecoder());
		//pipeline.addLast("encoder", new ByteBufferEncoder());
		
		pipeline.addLast("decoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0 ,4));
		pipeline.addLast("encoder", new LengthFieldPrepender(4));
		/**
		 * 减少woker占用时间。使用的事1
		 * 1、messageReceived方法启动新线程
		 * 2、ChannelPipeline添加executor （下面注释部分）
		 */
		
//		// 一个保证来自相同通道的事件能够顺序的执行的 int corePoolSize,long maxChannelMemorySize 1M,long maxTotalMemorySize 10M
//		ThreadPoolExecutor executor = new OrderedMemoryAwareThreadPoolExecutor(poolsize, 1048576, 10485760);
//		executor.setThreadFactory(new NettyExecutorThreadFactory());// 生成netty-worker-thread  atom 线程
//		// 转发一个上游ChannelEvent到一个Executor.
//		// 当你的ChannelHandler执行一个需要长时间阻塞操作或访问一个非CPU绑定的业务逻辑如数据库访问时ExecutionHandler经常被使用.
//		// 在一个管道里没有使用ExecutionHandler 的运行这些操作会导致在I/O期间出现间断,因为一个I/O线程不能执行I/O,除非你的处理器返回控制权给I/O线程.
//		// 大多数情况下,一个ExecutionHandler和 OrderedMemoryAwareThreadPo	:OolExecutor是成对出现的,因为它保证事件执行的正确顺序和防止加载出现 OutOfMemoryError
//		pipeline.addLast("executor", new ExecutionHandler(executor));
		
		
		//指定时间没读写操作触发一个 IdleStateEvent 事件.
		pipeline.addLast("timeout", idleStateHandler);
		
		pipeline.addLast("executor", executionHandler);
		pipeline.addLast("handler", new SessionHandler());
		return pipeline;
	}

	public int getSessionIdleTime() {
		return sessionIdleTime;
	}

	public void setSessionIdleTime(int sessionIdleTime) {
		this.sessionIdleTime = sessionIdleTime;
	}

}
